home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Text / Edit / GoldED-Demo / installdata / golded / developer / source / quickstarter / ed.c next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  16.8 KB  |  732 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.   Quick starter, ©1999 Dietmar Eilert.
  4.  
  5.   This is the C source code of the quickstarter. It demonstrates how to address
  6.   the editor from other applications.
  7.  
  8.   DICE (important: compile as resident/pure program !):
  9.  
  10.   dcc ed.c rawdofmt.asm -// -proto -mRR -mi -pr -3.0 -o ed
  11.  
  12.   ------------------------------------------------------------------------------
  13. */
  14.  
  15. /// "compiler"
  16.  
  17. #ifdef __SASC
  18.  
  19. #define __USE_SYSBASE
  20. #define __geta4      __saveds
  21. #define __stkargs    __stdargs
  22.  
  23. #define __A0         register __a0
  24. #define __A1         register __a1
  25. #define __A2         register __a2
  26. #define __A3         register __a3
  27. #define __A4         register __a4
  28. #define __A5         register __a5
  29. #define __A6         register __a6
  30. #define __A7         register __a7
  31. #define __D0         register __d0
  32. #define __D1         register __d1
  33. #define __D2         register __d2
  34. #define __D3         register __d3
  35. #define __D4         register __d4
  36. #define __D5         register __d5
  37. #define __D6         register __d6
  38. #define __D7         register __d7
  39.  
  40. #endif
  41.  
  42. #ifdef _DCC
  43.  
  44. #define __asm
  45.  
  46. #endif
  47.  
  48. ///
  49. /// "includes"
  50.  
  51. #include <exec/exec.h>
  52. #include <string.h>
  53. #include <stdio.h>
  54. #include <string.h>
  55. #include <stdlib.h>
  56. #include <stdarg.h>
  57. #include <intuition/intuition.h>
  58. #include <dos/dos.h>
  59. #include <dos/dosextens.h>
  60. #include <dos/rdargs.h>
  61. #include <dos/dostags.h>
  62. #include <workbench/startup.h>
  63. #include <workbench/workbench.h>
  64. #include <rexx/errors.h>
  65. #include <rexx/rxslib.h>
  66.  
  67. // prototypes
  68.  
  69. #include <clib/alib_protos.h>
  70. #include <clib/dos_protos.h>
  71. #include <clib/exec_protos.h>
  72. #include <clib/icon_protos.h>
  73. #include <clib/intuition_protos.h>
  74. #include <clib/rexxsyslib_protos.h>
  75. #include <clib/utility_protos.h>
  76. #include <clib/wb_protos.h>
  77.  
  78. // pragmas
  79.  
  80. #ifdef __SASC
  81.  
  82. #include <pragmas/dos_pragmas.h>
  83. #include <pragmas/exec_sysbase_pragmas.h>
  84. #include <pragmas/icon_pragmas.h>
  85. #include <pragmas/intuition_pragmas.h>
  86. #include <pragmas/rexxsyslib_pragmas.h>
  87. #include <pragmas/utility_pragmas.h>
  88. #include <pragmas/wb_pragmas.h>
  89.  
  90. #endif
  91.  
  92. ///
  93. /// "defines"
  94.  
  95. #define Prototype        extern
  96. #define MAX_PATHLEN      512
  97. #define MAX_CMDLEN       256
  98. #define ARGBUFFER_SIZE   8192
  99. #define ARGBUFFER_LIMIT  8000
  100.  
  101. ///
  102. /// "globals"
  103.  
  104. extern struct Library *IconBase;
  105. extern struct Library *UtilityBase;
  106. extern struct Library *RexxSysBase;
  107. extern struct Library *DOSBase;
  108. extern struct Library *SysBase;
  109.  
  110. ///
  111. /// "prototypes"
  112.  
  113. Prototype int              Action         (UBYTE *, UBYTE *, BOOL, BOOL, ULONG *, UBYTE *, UBYTE *);
  114. Prototype UBYTE           *LookForEditor  (UBYTE *);
  115. Prototype int              main           (ULONG, UBYTE **);
  116. Prototype __stkargs UBYTE *myrawdofmt     (UBYTE *, UBYTE *, APTR);
  117. Prototype __stkargs UBYTE *mysprintf      (UBYTE *, UBYTE *, ...);
  118. Prototype LONG            *SendRexxCommand(UBYTE *, UBYTE *, struct MsgPort *, LONG *);
  119. Prototype UBYTE           *StartEditor    (UBYTE *, BOOL, UBYTE *, UBYTE *, UBYTE *);
  120. Prototype int              wbmain         (struct WBStartup *);
  121.  
  122. ///
  123. /// "globals"
  124.  
  125. #ifdef __SASC
  126.  
  127. UBYTE Version[] = "$VER: ed 3.9 " __AMIGADATE__ "\n\0";
  128.  
  129. #endif
  130.  
  131. #ifdef _DCC
  132.  
  133. UBYTE Version[] = "$VER: ed 3.9 (" __COMMODORE_DATE__ ")\n\0";
  134.  
  135. #endif
  136.  
  137. ///
  138. /// "entry points"
  139.  
  140. /* --------------------------------------- main --------------------------------
  141.  
  142.  CLI entry point. Parse command line - create a string <argBuffer> containing
  143.  provided  file  names  (file names are made absolute). This string has to be
  144.  FreeVec()'ed later on. Additionally, command line options are checked.
  145.  
  146. */
  147.  
  148. int
  149. main(argc, argv)
  150.  
  151. ULONG argc;
  152. UBYTE *argv[];
  153. {
  154.     int error;
  155.  
  156.     if (argc == 0) {
  157.  
  158.         error = wbmain((struct WBStartup *)argv);
  159.     }
  160.     else {
  161.  
  162.         UBYTE *argBuffer;
  163.  
  164.         error = 0;
  165.  
  166.         if (argBuffer = (UBYTE *)AllocVec(ARGBUFFER_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) {
  167.  
  168.             struct RDArgs *rdArgs;
  169.  
  170.             LONG args[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  171.  
  172.             if (rdArgs = ReadArgs("FILETYPE/K,Y=STICKY/S,F=FILE/M,HIDE/S,-STICKY/S,L=LINE/N,A=AREXX/K,SESSION/K", args, NULL)) {
  173.  
  174.                 if (args[2]) {                       // FILE/M
  175.  
  176.                     UBYTE *path;
  177.  
  178.                     if (path = (UBYTE *)AllocVec(MAX_PATHLEN, MEMF_PUBLIC | MEMF_CLEAR)) {
  179.  
  180.                         UBYTE **nextFile;
  181.                         BPTR    lock;
  182.  
  183.                         for (nextFile = (UBYTE **)args[2]; nextFile && *nextFile; ++nextFile) {
  184.  
  185.                             strcpy(path, *nextFile);
  186.  
  187.                             // expand file name
  188.  
  189.                             if (lock = Lock(path, ACCESS_READ)) {
  190.  
  191.                                 NameFromLock(lock, path, MAX_PATHLEN);
  192.  
  193.                                 UnLock(lock);
  194.                             }
  195.                             else if (strchr(path, ':') == NULL) {
  196.  
  197.                                 GetCurrentDirName(path, MAX_PATHLEN);
  198.  
  199.                                 AddPart(path, *nextFile, MAX_PATHLEN);
  200.                             }
  201.  
  202.                             strcat(argBuffer, "\42");
  203.  
  204.                             strcat(argBuffer, path);
  205.  
  206.                             strcat(argBuffer, "\42 ");
  207.  
  208.                             // too many files ?
  209.  
  210.                             if (strlen(argBuffer) > ARGBUFFER_LIMIT) {
  211.  
  212.                                 error = 5;
  213.  
  214.                                 break;
  215.                             }
  216.                         }
  217.  
  218.                         FreeVec(path);
  219.                     }
  220.                 }
  221.  
  222.                 if (error == 0)
  223.  
  224.                     error = Action(argBuffer, (UBYTE *)args[0], args[1] || args[4], (BOOL)args[3], (ULONG *)args[5], (UBYTE *)args[6], (UBYTE *)args[7]);
  225.  
  226.                 FreeArgs(rdArgs);
  227.             }
  228.             else
  229.                 error = 20;
  230.  
  231.             FreeVec(argBuffer);
  232.         }
  233.         else
  234.             error = 20;
  235.     }
  236.  
  237.     return(error);
  238. }
  239.  
  240.  
  241. /* ------------------------------------ wbmain ---------------------------------
  242.  
  243.  Workbench entry point. Read tooltypes of text icon(s) to decide whether user
  244.  prefers a special configuration.
  245.  
  246. */
  247.  
  248. int
  249. wbmain(wbs)
  250.  
  251. struct WBStartup *wbs;
  252. {
  253.     int    error;
  254.     UBYTE *argBuffer;
  255.  
  256.     if (argBuffer = (UBYTE *)AllocVec(ARGBUFFER_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) {
  257.  
  258.         struct DiskObject *diskObject = NULL;
  259.  
  260.         UBYTE *filetype;
  261.         UBYTE *arexx;
  262.         UBYTE *session;
  263.         BOOL   hide;
  264.  
  265.         error = 0;
  266.  
  267.         filetype = NULL;
  268.         arexx    = NULL;
  269.         session  = NULL;
  270.  
  271.         hide = FALSE;
  272.  
  273.         if (--wbs->sm_NumArgs) {
  274.  
  275.             UBYTE *path;
  276.  
  277.             if (path = (UBYTE *)AllocVec(MAX_PATHLEN, MEMF_PUBLIC | MEMF_CLEAR)) {
  278.  
  279.                 struct WBArg *wbArg = wbs->sm_ArgList;
  280.  
  281.                 while ((wbs->sm_NumArgs)--) {
  282.  
  283.                     ++wbArg;
  284.  
  285.                     NameFromLock(wbArg->wa_Lock, path, MAX_PATHLEN);
  286.  
  287.                     AddPart(path, wbArg->wa_Name, MAX_PATHLEN);
  288.  
  289.                     // options not yet read ?
  290.  
  291.                     if (diskObject == NULL) {
  292.  
  293.                         if (diskObject = GetDiskObject(path)) {
  294.  
  295.                             filetype = FindToolType(diskObject->do_ToolTypes, "FILETYPE");
  296.                             arexx    = FindToolType(diskObject->do_ToolTypes, "AREXX"   );
  297.                             session  = FindToolType(diskObject->do_ToolTypes, "SESSION" );
  298.  
  299.                             if (FindToolType(diskObject->do_ToolTypes, "HIDE"))
  300.  
  301.                                 hide = TRUE;
  302.                         }
  303.                     }
  304.  
  305.                     strcat(argBuffer, "\42");
  306.  
  307.                     strcat(argBuffer, path);
  308.  
  309.                     strcat(argBuffer, "\42 ");
  310.  
  311.                     // too many files ?
  312.  
  313.                     if (strlen(argBuffer) > ARGBUFFER_LIMIT) {
  314.  
  315.                         error = 5;
  316.  
  317.                         break;
  318.                     }
  319.                 }
  320.  
  321.                 FreeVec(path);
  322.             }
  323.             else
  324.                 error = 20;
  325.         }
  326.  
  327.         if (error == 0)
  328.  
  329.             error = Action(argBuffer, filetype, FALSE, hide, NULL, arexx, session);
  330.  
  331.         if (diskObject)
  332.  
  333.             FreeDiskObject(diskObject);
  334.  
  335.         FreeVec(argBuffer);
  336.     }
  337.     else
  338.         error = 20;
  339.  
  340.     return(error);
  341. }
  342.  
  343. ///
  344. /// "main routine"
  345.  
  346. /* ------------------------------------ Action ---------------------------------
  347.  
  348.  Run editor if no running instance is found (note: running the editor will
  349.  open a first window, i.e. no need to open a further one unless files are
  350.  specified). Send LOCK message to running editor. Wait for positive reply,
  351.  pass our list of <files> to that editor, unlock editor (use delayed unlock
  352.  if <sticky> is specified). Files are passed to the editor as startup options
  353.  if STICKY is not specified and if there is no running editor instance.
  354.  
  355. */
  356.  
  357. int
  358. Action(files, filetype, sticky, hide, line, arexx, session)
  359.  
  360. UBYTE  *files, *filetype, *arexx, *session;
  361. ULONG  *line;
  362. BOOL    hide, sticky;
  363. {
  364.     int    error;
  365.     UBYTE *buffer;
  366.  
  367.     error = 0;
  368.  
  369.     if (buffer = (UBYTE *)AllocVec(MAX_PATHLEN, MEMF_PUBLIC | MEMF_CLEAR)) {
  370.  
  371.         UBYTE *host;
  372.         LONG   result;
  373.  
  374.         if (host = LookForEditor(arexx)) {               // editor found ?
  375.  
  376.              struct MsgPort *replyPort;
  377.  
  378.              if (replyPort = CreateMsgPort()) {
  379.  
  380.                 if (session) {
  381.  
  382.                     mysprintf(buffer, "SESSION LOAD CONFIG=\42%s\42", session);
  383.  
  384.                     SendRexxCommand(host, buffer, replyPort, &result);
  385.                 }
  386.                 else if (*files) {
  387.  
  388.                     if (SendRexxCommand(host, "LOCK CURRENT RELEASE=4", replyPort, &result)) {
  389.  
  390.                         if (result == RC_OK) {
  391.  
  392.                             if (*files) {
  393.  
  394.                                 strins(files, "NAME ");
  395.  
  396.                                 if (filetype) {
  397.  
  398.                                     mysprintf(buffer, "FILETYPE=\42%s\42 ", filetype);
  399.  
  400.                                     strins(files, buffer);
  401.                                 }
  402.  
  403.                                 strins(files, "OPEN SMART QUIET ");
  404.                             }
  405.                             else
  406.                                 strcpy(files, "MORE SMART");
  407.  
  408.                             SendRexxCommand(host, files, replyPort, &result);
  409.  
  410.                             if (line) {
  411.  
  412.                                 mysprintf(buffer, "GOTO LINE=%ld UNFOLD=TRUE", *(ULONG *)line);
  413.  
  414.                                 SendRexxCommand(host, buffer, replyPort, &result);
  415.                             }
  416.  
  417.                             SendRexxCommand(host, sticky ? "UNLOCK STICKY" : "UNLOCK", replyPort, &result);
  418.                         }
  419.                     }
  420.                     else
  421.                         error = 20;
  422.                 }
  423.                 else {
  424.  
  425.                     // editor might be iconified - send wake-up-command (any command will work)
  426.  
  427.                     SendRexxCommand(host, "SCREEN FRONT", replyPort, &result);
  428.                 }
  429.  
  430.                 DeleteMsgPort(replyPort);
  431.             }
  432.             else
  433.                 error = 20;
  434.         }
  435.         else if (host = StartEditor(arexx, hide, filetype, files, session)) {
  436.  
  437.             if (line) {
  438.  
  439.                 struct MsgPort *replyPort;
  440.  
  441.                 if (replyPort = CreateMsgPort()) {
  442.  
  443.                     mysprintf(buffer, "GOTO LINE=%ld UNFOLD=TRUE", *(ULONG *)line);
  444.  
  445.                     SendRexxCommand(host, buffer, replyPort, &result);
  446.  
  447.                     DeleteMsgPort(replyPort);
  448.                 }
  449.                 else
  450.                     error = 20;
  451.             }
  452.  
  453.             if (sticky) {
  454.  
  455.                 struct MsgPort *replyPort;
  456.  
  457.                 if (replyPort = CreateMsgPort()) {
  458.  
  459.                     if (SendRexxCommand(host, "LOCK CURRENT RELEASE=4", replyPort, &result)) {
  460.  
  461.                         SendRexxCommand(host, "UNLOCK STICKY", replyPort, &result);
  462.                     }
  463.                     else
  464.                         error = 20;
  465.  
  466.                     DeleteMsgPort(replyPort);
  467.                 }
  468.                 else
  469.                     error = 20;
  470.             }
  471.         }
  472.         else
  473.             error = 20;
  474.  
  475.         FreeVec(buffer);
  476.     }
  477.     else
  478.         error = 20;
  479.  
  480.     return(error);
  481. }
  482.  
  483. ///
  484. /// "misc"
  485.  
  486. /* ----------------------------------- mysprintf -------------------------------
  487.  
  488.  sprintf replacement
  489.  
  490. */
  491.  
  492. __stkargs UBYTE *
  493. mysprintf(UBYTE *buffer, UBYTE *template, ...)
  494. {
  495.     myrawdofmt(buffer, template, (APTR)((ULONG)&template + sizeof(ULONG)));
  496.  
  497.     return(buffer);
  498. }
  499.  
  500.  
  501. /* -------------------------------- LookForEditor ------------------------------
  502.  
  503.  Look for running editor task.
  504.  
  505. */
  506.  
  507. UBYTE *
  508. LookForEditor(host)
  509.  
  510. UBYTE *host;
  511. {
  512.     UBYTE *name = NULL;
  513.  
  514.     Forbid();
  515.  
  516.     if (host && FindPort(host))
  517.  
  518.         name = host;
  519.  
  520.     else {
  521.  
  522.         const UBYTE *try[] = { "GOLDED.1", "GOLDED.2", "GOLDED.3", "GOLDED.4", "GOLDED.5", NULL };
  523.  
  524.         UBYTE **next;
  525.  
  526.         for (next = (UBYTE **)try; *next; ++next) {
  527.  
  528.             if (FindPort(*next)) {
  529.  
  530.                 name = *next;
  531.  
  532.                 break;
  533.             }
  534.         }
  535.     }
  536.  
  537.     Permit();
  538.  
  539.     return(name);
  540. }
  541.  
  542.  
  543. /* ----------------------------------- StartEditor -----------------------------
  544.  
  545.  Launch a new editor task. Look for editor assign. Create assign if none is
  546.  found (assign[] is set by the GoldED installer script). Return pointer to
  547.  host name (or NULL).
  548.  
  549. */
  550.  
  551. UBYTE *
  552. StartEditor(rexxname, hide, filetype, files, session)
  553.  
  554. UBYTE *rexxname;
  555. UBYTE *filetype;
  556. UBYTE *files;
  557. UBYTE *session;
  558. BOOL   hide;
  559. {
  560.     UBYTE *buffer;
  561.     UBYTE *host;
  562.  
  563.     host = NULL;
  564.  
  565.     if (buffer = (UBYTE *)AllocVec(MAX_PATHLEN, MEMF_PUBLIC | MEMF_CLEAR)) {
  566.  
  567.         UBYTE *command;
  568.  
  569.         if (command = (UBYTE *)AllocVec(MAX_CMDLEN, MEMF_PUBLIC | MEMF_CLEAR)) {
  570.  
  571.             struct MsgPort *port;
  572.             struct Task    *task;
  573.             UBYTE          *cmd;
  574.             LONG            stack;
  575.  
  576.             task = FindTask(NULL);
  577.  
  578.             // determine current stack size (used as default for running editor)
  579.  
  580.             stack = (ULONG)task->tc_SPUpper - (ULONG)task->tc_SPLower;
  581.  
  582.             if (stack < 8192)                        // minimum 8 KB
  583.  
  584.                 stack = 8192;
  585.                                                      // maximum 128 KB
  586.             if (stack > 131072)
  587.  
  588.                 stack = 131072;
  589.  
  590.             if (session) {
  591.  
  592.                 mysprintf(command, "SESSION=\42%s\42", session);
  593.  
  594.                 cmd = command;
  595.             }
  596.             else if (files) {
  597.  
  598.                 cmd = files;
  599.             }
  600.             else {
  601.  
  602.                 cmd = command;
  603.             }
  604.  
  605.             if (filetype) {
  606.  
  607.                 mysprintf(buffer, "FILETYPE=\42%s\42 ", filetype);
  608.  
  609.                 strins(cmd, buffer);
  610.             }
  611.  
  612.             if (rexxname) {
  613.  
  614.                 host = rexxname;
  615.  
  616.                 mysprintf(buffer, "AREXX=\42%s\42 ", rexxname);
  617.  
  618.                 strins(cmd, buffer);
  619.             }
  620.             else
  621.                 host = "GOLDED.1";
  622.  
  623.             if (hide)
  624.  
  625.                 strins(cmd, "HIDE ");
  626.  
  627.             strins(cmd, "golded:golded ");
  628.  
  629.             port = NULL;
  630.  
  631.             if (SystemTags(cmd, SYS_Asynch, TRUE, SYS_Input, NULL, SYS_Output, NULL, NP_StackSize, stack, TAG_DONE) == 0) {
  632.  
  633.                 UWORD           try;
  634.  
  635.                 for (try = 100; try--; Delay(10)) {
  636.  
  637.                     Forbid();
  638.  
  639.                     port = FindPort(host);
  640.  
  641.                     Permit();
  642.  
  643.                     if (port)
  644.  
  645.                         break;
  646.                 }
  647.             }
  648.  
  649.             if (port == NULL)
  650.  
  651.                 host = NULL;
  652.  
  653.             FreeVec(command);
  654.         }
  655.  
  656.         FreeVec(buffer);
  657.     }
  658.  
  659.     return(host);
  660. }
  661.  
  662. ///
  663. /// "rexx"
  664.  
  665. /* ---------------------------------- SendRexxCommand -------------------------
  666.  
  667.  Send ARexx message & wait for answer. Return pointer to result or NULL.
  668.  
  669. */
  670.  
  671. LONG *
  672. SendRexxCommand(port, cmd, replyPort, result)
  673.  
  674. struct MsgPort *replyPort;
  675. UBYTE          *cmd;
  676. UBYTE          *port;
  677. LONG           *result;
  678. {
  679.     struct MsgPort *rexxport;
  680.  
  681.     Forbid();
  682.  
  683.     if (rexxport = FindPort(port)) {
  684.  
  685.         struct RexxMsg *rexxMsg, *answer;
  686.  
  687.         if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
  688.  
  689.             if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
  690.  
  691.                 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
  692.  
  693.                 PutMsg(rexxport, &rexxMsg->rm_Node);
  694.  
  695.                 *result = 0;
  696.  
  697.                 do {
  698.                     
  699.                     WaitPort(replyPort);
  700.  
  701.                     if (answer = (struct RexxMsg *)GetMsg(replyPort))
  702.  
  703.                         *result = answer->rm_Result1;
  704.  
  705.                 } while (answer == NULL);
  706.  
  707.                 Permit();
  708.  
  709.                 if (answer->rm_Result1 == RC_OK) 
  710.  
  711.                     if (answer->rm_Result2)
  712.  
  713.                         DeleteArgstring((UBYTE *)answer->rm_Result2);
  714.  
  715.                 DeleteArgstring((UBYTE *)ARG0(answer));
  716.  
  717.                 DeleteRexxMsg(answer);
  718.  
  719.                 return(result);
  720.             }
  721.             else
  722.                 DeleteRexxMsg(rexxMsg);
  723.         }
  724.     }
  725.  
  726.     Permit();
  727.  
  728.     return(NULL);
  729. }
  730.  
  731. ///
  732.